package cn.chrilwe.pigpig.im.server.handler;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

import com.alibaba.fastjson.JSON;

import cn.chrilwe.pigpig.core.base.Code;
import cn.chrilwe.pigpig.core.base.ResMsg;
import cn.chrilwe.pigpig.im.filters.Filter;
import cn.chrilwe.pigpig.im.protocol.TalkRequest;
import cn.chrilwe.pigpig.im.protocol.TalkResponse;
import cn.chrilwe.pigpig.im.server.WebSocketServer;
import cn.chrilwe.pigpig.im.service.TopicMessageService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

/**
 * 
 * @author chrilwe
 * 2020-7-26
 */
public class MessageHandler extends SimpleChannelInboundHandler<TalkRequest> {
	
	private static final String Channel = null;

	public static Map<String, Channel> channels = new HashMap<String, Channel>();
	
	public static Map<String, Map> groupChannel = new HashMap<String,Map>();
	
	public static Map<String, String> channelIdAndClientIdMap = new HashMap<String, String>();
	
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, TalkRequest msg) throws Exception {
		if(msg == null || msg.getRoomId() <= 0) {
			TalkResponse res = new TalkResponse();
			res.setStatus(Code.PROTOCOL_ERR);
			res.setResMsg(ResMsg.PROTOCOL_ERR);
			ChannelFuture cf = ctx.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(res)));
			boolean success = cf.isSuccess();
			if(success) {
				ctx.close();
			}
		} else {
			getOrSetGroupChannel(ctx, msg.getRoomId()+"");
			
			//执行过滤器
			TalkResponse response = invokeFilters(WebSocketServer.sortFilters,msg);
			
			TopicMessageService topicMsgService = (TopicMessageService) WebSocketServer.applicationContext.getBean("topicMessageService");
			TalkResponse res = topicMsgService.topicMsg(msg);
			if(res.getStatus() == Code.SUCCESS) {
				Map<String, Channel> map = groupChannel.get(msg.getRoomId()+"");
				Set<Entry<String, Channel>> entrySet = map.entrySet();
				for (Entry<String, Channel> entry : entrySet) {
					String clientId = entry.getKey();
					Channel ch = entry.getValue();
					ch.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(res)));
				}
			} else {
				ctx.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(res)));
			}
		}
	}
	
	//客户端连接成功
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		String clientId = UUID.randomUUID().toString();
		channels.put(clientId, ctx.channel());
		channelIdAndClientIdMap.put(ctx.channel().id().toString(), clientId);
	}
	

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		
	}
	
	
	protected TalkResponse invokeFilters(List<Filter> sortFilters, TalkRequest talkRequest) {
		if(sortFilters.size() <= 0) {
			return null;
		}
		for(int i=0; i<sortFilters.size()-1; i++) {
			Filter filter = sortFilters.get(i);
			TalkResponse doChain = filter.doChain(talkRequest);
			if(doChain != null) {
				return doChain;
			}
		}
		return null;
	}
	
	@SuppressWarnings("rawtypes")
	protected void getOrSetGroupChannel(ChannelHandlerContext ctx, String roomId) {
		Map map = groupChannel.get(roomId);
		String clientId = channelIdAndClientIdMap.get(ctx.channel().id().toString());
		if(map != null) {
			Channel c = (Channel)map.get(clientId);
			if(c == null) {
				map.put(clientId, ctx.channel());
			}
			return;
		}
		Map<String, Channel> v = new HashMap<String, Channel>();
		v.put(clientId, ctx.channel());
		groupChannel.put(roomId, v);
	}
}
